# Times
#

import time
import signal
import functools



class TimeoutError(Exception): pass


class timer(object):
    """<1> with zt.timer(name) as t:
       <2> t.checkpoint(note)
    """
    def __init__(self, name='t'):
        self.name = name
        self.begin = time.time()
    @property
    def elapsed(self):
        return time.time() - self.begin
    def checkpoint(self, point=''):
        print('─○─ function <%s> took %.6f seconds.'
              % (self.name, self.elapsed))
    def __enter__(self):
        print('@timer %s launched.' % self.name)
        return self
    def __exit__(self, type, value, traceback):
        print('─○─ total time cost: %.6f seconds.' % self.elapsed)
        print('@timer %s finished.' % self.name)


def timeit(func):
    def _deco(*args, **kw):
        begin = time.time()
        result = func(*args, **kw)
        print('─○─ function "%s" tool %.6f seconds.'
              % (func.__name__, time.time() - begin))
        return result
    return _deco


def timeout(seconds, err='Time out!'):
    '''Set timeout for the funcall.'''
    def decorated(func):
        def _handle_timeout(signum, frame):
            raise TimeoutError(err)
        def wrapper(*args, **kw):
            signal.signal(signal.SIGALRM, _handle_timeout)
            signal.alarm(seconds)
            try:
                result = func(*args, **kw)
            finally:
                signal.alarm(0)
            return result
        return functools.wraps(func)(wrapper)
    return decorated
